package com.example.controller;

import com.example.dto.AnnouncementRequest;
import com.example.dto.ApiResponse;
import com.example.entity.Announcement;
import com.example.service.AnnouncementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.*;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.validation.Valid;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/announcements")
public class AnnouncementController {

    @Autowired
    private AnnouncementService announcementService;

    /**
     * 获取已发布的公告列表
     * 该接口用于获取系统中所有已发布的公告信息，并封装成ApiResponse对象返回
     *
     * @return ApiResponse<List<Announcement>> 包含已发布公告列表的ApiResponse对象
     */
    /*@GetMapping("/public")
    public ApiResponse<List<Announcement>> getPublishedAnnouncements() {
        return ApiResponse.success("Success", announcementService.getAllPublishedAnnouncements());
    }
*/
    @GetMapping("/public")
    public ApiResponse<?> getPublishedAnnouncements(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size) {
        Map<String, Object> pageResult = announcementService.getPublishedAnnouncementsWithPage(page, size);
        return ApiResponse.success("获取公开公告成功", pageResult);
    }
    /**
     * 根据ID获取公告详情
     * 该接口通过公告的ID查询并返回公告的详细信息。
     *
     * @param id 公告的唯一标识符
     * @return 如果查询成功，返回包含公告详情的ApiResponse对象；如果公告不存在，返回包含错误信息的ApiResponse对象
     */
    @GetMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN') or hasRole('TEACHER') or hasRole('USER') ")
    public ApiResponse<?> getAnnouncementById(@PathVariable Long id) {
        return announcementService.getAnnouncementWithFiles(id);
    }

    /**
     * 获取所有公告
     * 该接口用于获取系统中所有的公告信息，支持分页和按状态筛选，仅管理员和教师角色可访问。
     *
     * @param page 分页码，从1开始，默认为1
     * @param size 每页显示的公告数量，默认为10
     * @param status 公告状态，可选参数，用于筛选特定状态的公告
     * @return ApiResponse<Map<String, Object>> 包含所有公告的分页结果响应对象
     */
    @GetMapping
    @PreAuthorize("hasRole('ADMIN') or hasRole('TEACHER')")
    public ApiResponse<?> getAllAnnouncements(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(required = false) Integer status) {
        Map<String, Object> pageResult = announcementService.getAllAnnouncementsWithPage(page, size, status);
        return ApiResponse.success("获取公告列表成功", pageResult);
    }

    /**
     * 创建公告
     * 该接口用于创建新的公告，只有拥有ADMIN或TEACHER角色的用户可以调用
     *
     * @param request 公告请求对象，包含创建公告所需的信息
     * @return ApiResponse对象，包含操作结果及相关数据
     */
    @PostMapping
    @PreAuthorize("hasRole('ADMIN') or hasRole('TEACHER')")
    public ApiResponse<?> createAnnouncement(
            @RequestPart("announcement") @Valid AnnouncementRequest request,
            @RequestPart(value = "files", required = false) List<MultipartFile> files) {
        return announcementService.createAnnouncementWithFiles(request, files);
    }

    /**
     * 更新公告接口
     * 根据公告ID更新公告信息，需要管理员或版主权限
     *
     * @param id       公告的唯一标识符
     * @param request  包含更新公告所需信息的请求体
     * @return 返回操作结果的API响应对象
     */
    @PutMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN') or hasRole('TEACHER')")
    public ApiResponse<?> updateAnnouncement(
            @PathVariable Long id,
            @Valid @RequestBody AnnouncementRequest request) {
        return announcementService.updateAnnouncement(id, request);
    }

    /**
     * 删除公告接口
     * 根据公告ID删除对应的公告信息，需要管理员或版主权限
     *
     * @param id 公告的唯一标识符
     * @return 返回操作结果的API响应对象
     */
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN') or hasRole('TEACHER')")
    public ApiResponse<?> deleteAnnouncement(@PathVariable Long id) {
        return announcementService.deleteAnnouncement(id);
    }

    /**
     * 发布或取消发布公告
     * 根据传入的公告ID和发布状态，发布或取消发布公告
     *
     * @param id 公告的唯一标识符
     * @param isPublished 发布状态，true表示发布，false表示取消发布
     * @return 返回操作结果的API响应对象
     */
    @PutMapping("/{id}/publish")
    @PreAuthorize("hasRole('ADMIN') or hasRole('TEACHER')")
    public ApiResponse<?> publishAnnouncement(
            @PathVariable Long id,
            @RequestParam Boolean isPublished) {
        return announcementService.togglePublishStatus(id, isPublished);
    }

    @GetMapping("/files/{fileId}/download")
    public ResponseEntity<Resource> downloadFile(@PathVariable Long fileId) {
        return announcementService.downloadFile(fileId);
    }
    
    /**
     * 获取文件访问URL
     * 该接口通过文件ID获取可访问的URL
     *
     * @param fileId 文件ID
     * @return 包含文件URL的API响应
     */
    @GetMapping("/files/{fileId}/url")
    public ApiResponse<?> getFileUrl(@PathVariable Long fileId) {
        String url = announcementService.getFileUrl(fileId);
        return ApiResponse.success("获取文件URL成功", url);
    }
    
    /**
     * 直接查看文件（在浏览器中打开）
     * 该接口通过文件ID在浏览器中直接查看/预览文件
     *
     * @param fileId 文件ID
     * @return 文件资源响应
     */
    @GetMapping("/files/{fileId}/view")
    public ResponseEntity<Resource> viewFile(@PathVariable Long fileId) {
        return announcementService.viewFile(fileId);
    }
}